﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Prism.Events;
using ServerConnection;
using ServerConnection.ShopServiceReference;
using System.Collections.ObjectModel;
using ModuleExternalProducersAdd.Commands;
using System.Windows.Input;
using EventInfrastructure;

namespace ModuleExternalProducersAdd.ViewModels
{
    public class ProducerAddViewModel : IProducerAddViewModel, INotifyPropertyChanged
    {

        #region Private members

        private IEventAggregator m_eventAggregator;

        /// <summary>
        /// List of categories
        /// </summary>
        private ObservableCollection<CategoryView> m_categories;

        /// <summary>
        /// List of subcategories
        /// </summary>
        private ObservableCollection<CategoryView> m_subCategories;

        /// <summary>
        /// List of products
        /// </summary>
        private List<ProductView> m_products;

        /// <summary>
        /// Selected category
        /// </summary>
        private CategoryView m_selectedCategory;

        /// <summary>
        /// Selected subcategory
        /// </summary>
        private CategoryView m_selectedSubCategory;

        /// <summary>
        /// Name of adding producer
        /// </summary>
        private string m_producerName = string.Empty;

        /// <summary>
        /// List of added products to producer
        /// List is used just for displaying products in view
        /// Clears after saving a new producer
        /// </summary>
        private ObservableCollection<ProductView> m_addedProducts = new ObservableCollection<ProductView>();

        /// <summary>
        /// List of added product ids, used for saving on server.
        /// Clears after saving a new producer
        /// </summary>
        private List<long> m_addedProductId = new List<long>();

        /// <summary>
        /// Selected product in the ListBox
        /// </summary>
        private ProductView m_selectedProduct;

        private AddProductToProducerCommand m_addProductToProducerCommand;

        private SaveNewProducerCommand m_saveNewProducerCommand;


        #endregion Private members



        #region Private methods

        /// <summary>
        /// This method is called up when the property is changed
        /// </summary>
        /// <param name="propertyName"></param>
        private void m_OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                //fire event
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion Private methods


        [Dependency]
        public IRegionManager RegionManager { get; set; }



        #region Constructor

        public ProducerAddViewModel(IEventAggregator eventAggregator)
        {
            this.m_eventAggregator = eventAggregator;

            ///create commands, pass the viewmodel
            m_addProductToProducerCommand = new Commands.AddProductToProducerCommand(this);
            m_saveNewProducerCommand = new Commands.SaveNewProducerCommand(this);

            ///update current category list           
            List<CategoryView> cats = Service.Instance.GetCategories("eng", 0).ToList(); 
            ///convert list 2 obervable
            ObservableCollection<CategoryView> catsObserv = new ObservableCollection<CategoryView>(cats);
            ///update categories on form
            LoadCategories = catsObserv;
              
        }

        #endregion Constructor



        #region Public properties

        /// <summary>
        /// Property changes, when user selects concrete producer and then get categories
        /// </summary>
        public ObservableCollection<CategoryView> LoadCategories
        {
            get
            {
                return m_categories;
            }
            set
            {
                m_categories = value;
                m_OnPropertyChanged("LoadCategories");
            }
        }


        public ObservableCollection<CategoryView> LoadSubCategories
        {
            get
            {
                return m_subCategories;
            }
            set
            {
                m_subCategories = value;
                m_OnPropertyChanged("LoadSubCategories");
            }
        }

        /// <summary>
        /// Products are loaded when subcategory is chosen
        /// </summary>
        public List<ProductView> LoadProducts
        {
            get
            {
                return m_products;
            }
            set
            {
                m_products = value;
                m_OnPropertyChanged("LoadProducts");
            }
        }

        /// <summary>
        /// Binds to ListBox of added products
        /// </summary>
        public ObservableCollection<ProductView> AddedProducts
        {
            get
            {
                return m_addedProducts;
            }
            set
            {
                m_addedProducts = value;
                m_OnPropertyChanged("AddedProducts");
            }
        }

        /// <summary>
        /// Add Product To Producer Command
        /// </summary>
        public AddProductToProducerCommand AddProductToProducerCommand
        {
            get
            {
                return m_addProductToProducerCommand;
            }
            set
            {
                m_addProductToProducerCommand = value;
            }
        }

        /// <summary>
        /// Save new Producer to db Command
        /// </summary>
        public SaveNewProducerCommand SaveNewProducerCommand
        {
            get
            {
                return m_saveNewProducerCommand;  
            }
            set
            {
                m_saveNewProducerCommand = value;
            }
        }


        /// <summary>
        /// Uses when category isselected
        /// </summary>
        public CategoryView OnSelectedCategory
        {
            get { return m_selectedCategory; }
            set
            {
                m_selectedCategory = value;
                if (m_selectedCategory != null)
                {
                    ///update current category list           
                    List<CategoryView> subCats = Service.Instance.GetCategories("eng", m_selectedCategory.Id).ToList();
                    ///convert list 2 obervable
                    ObservableCollection<CategoryView> subCategoriesObserv = new ObservableCollection<CategoryView>(subCats);

                    ///update combobox with subcategories
                    LoadSubCategories = subCategoriesObserv;

                    m_OnPropertyChanged("OnSelectedCategory");
                }
            }
        }

        /// <summary>
        /// Uses whensubcategory is selected
        /// </summary>
        public CategoryView OnSelectedSubCategory
        {
            get { return m_selectedSubCategory; }
            set
            {
                m_selectedSubCategory = value;
                if (m_selectedSubCategory != null)
                {
                    Dictionary<ProductFilter, object> filter = new Dictionary<ProductFilter, object>();
                    filter.Add(ProductFilter.Non, 0);

                    this.LoadProducts = Service.Instance.GetProductsOnPage(m_selectedSubCategory.Id, "eng", ProductSort.NameAsc, 0, 10, filter).ToList();

                    m_OnPropertyChanged("OnSelectedSubCategory");
                }
            }
        }

        /// <summary>
        /// Used when a product is selected in the listbox
        /// Then selected product issupposed to be added to the producer
        /// </summary>
        public ProductView OnSelectedProduct
        {
            get { return m_selectedProduct; }
            set
            {
                m_selectedProduct = value;

                if (m_selectedProduct != null)
                {
                    
                }
            }
        }

        /// <summary>
        /// Used when the name of a new producer is being typed in
        /// </summary>
        public string ProducerName
        {
            get { return m_producerName; }
            set { m_producerName = value; }
        }

        /// <summary>
        /// Used when description of producer is being typed in
        /// </summary>
        public string ProducerDescription
        {
            get;
            set;
        }

        #endregion Public properties



        #region PublicMethods

        /// <summary>
        /// Add selected product to the list of producer's products, if doesn't exists
        /// </summary>
        public void AddProductToProducer()
        {          
            ///search product in the lists of added products
            ProductView selectedProduct = AddedProducts.Where(x => x.Id == OnSelectedProduct.Id).FirstOrDefault();

            ///if product hasn't added yet
            if (selectedProduct == null)
            {
                ///Add id of product to list
                m_addedProductId.Add(OnSelectedProduct.Id);

                ///Add selected product to the list of producer's products
                AddedProducts.Add(OnSelectedProduct);
            }                        
        }

        public void SaveNewProducer()
        {
            ///TMP!!!
            ExternalProducerView externalProducer = new ExternalProducerView();

            externalProducer.Name = ProducerName;
            externalProducer.Description = ProducerDescription;

            ///validation
            if (externalProducer.Name.Length < 2)
            {
                return;
            }

            ///save producer and it's products
            Service.Instance.AddProducer(externalProducer, m_addedProductId.ToArray());

            ///clear list of product ids
            m_addedProductId.Clear();
            ///clear list of added products
            AddedProducts.Clear();

            ///publish the event
            ///Update producer ListBox in the Left region
            ///1 - not used
            m_eventAggregator.GetEvent<ProducerAddEvent>().Publish(1);
        }

        #endregion PublicMethods                         

        #region Events

        /// <summary>
        /// PropertyChanged is needed for binding to ui
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion Events
    }
}
